home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / Xconq 7.0d16 / Xconq 7.0d16 src / src / write.c < prev   
Encoding:
Text File  |  1993-12-20  |  40.3 KB  |  410 lines  |  [TEXT/MPS ]

  1. (BUFSIZE);
  2.     if (strlen(u_internal_name(u)) < strlen(typename)) {
  3.     typename = u_internal_name(u);
  4.     }
  5.     sprintf(shortestbuf, "%s", escaped_symbol(typename));
  6.     return shortestbuf;
  7. }
  8.  
  9. /* A saved game should include everything necessary to recreate a game
  10.    exactly.  It is important that this routine not attempt to use graphics,
  11.    since it may be called when graphics code fails. */
  12.  
  13. write_entire_game_state(fname)
  14. char *fname;
  15. {
  16.     Module *module = create_game_module(fname);
  17.     int rslt;
  18.  
  19.     module->filename = fname;
  20.     module->compresslayers = TRUE;
  21.     module->defall = TRUE;
  22.     rslt = write_game_module(module);
  23.     if (rslt) gamestatesafe = TRUE;
  24.     return rslt;
  25. }
  26.  
  27. /* Given a game module telling what is in the module, write out a file
  28.    containing the requested content.  Return true if everything went OK. */
  29.  
  30. write_game_module(module)
  31. Module *module;
  32. {
  33.     int i;
  34.     FILE *fp;
  35.     Obj *rest;
  36.  
  37.     if (escapedthing == NULL) escapedthing = xmalloc(BUFSIZE);
  38.     if ((fp = fopen(module->filename, "w")) != NULL) {
  39.     /* Write the definition of this game module. */
  40.     start_form(fp, key(K_GAME_MODULE));
  41.     add_to_form(fp, escaped_string(module->name));  newline_form(fp);
  42.     if (module->defall) {
  43.         write_str_prop(fp, key(K_TITLE), module->title,
  44.                "", 1, 0);
  45.         write_str_prop(fp, key(K_VERSION), module->version,
  46.                "", 1, 0);
  47.         write_str_prop(fp, key(K_BLURB), module->blurb,
  48.                "", 1, 0);
  49.         write_str_prop(fp, key(K_BASE_MODULE), module->basemodulename,
  50.                "", 1, 0);
  51.         write_str_prop(fp, key(K_PROGRAM_VERSION), version,
  52.                "", 1, 0);
  53.         /* etc */
  54.     }
  55.     newline_form(fp);
  56.     end_form(fp);  newline_form(fp);  newline_form(fp);
  57.     if (module->defall || module->deftypes)
  58.       write_types(fp, module);
  59.     if (module->defall || module->deftables)
  60.       write_tables(fp, module);
  61.     if (module->defall || module->defglobals)
  62.       write_globals(fp, module);
  63.     if (1 /* need to suppress synthesis after reload */) {
  64.       start_form(fp, key(K_SET));
  65.       add_to_form(fp, "synthesis-methods");
  66.       add_to_form(fp, "nil");
  67.       end_form(fp);
  68.       newline_form(fp);
  69.     }
  70.     if (module->defall || module->defscoring)
  71.       write_scorekeepers(fp, module);
  72.     doreshape = reshape_the_output(module);
  73.     reshaper = module;
  74.     if (module->defall || module->defworld)
  75.       write_world(fp, module);
  76.     if (module->defall || module->defareas)
  77.       write_areas(fp, module);
  78.     if (module->defall || module->defsides)
  79.       write_sides(fp, module);
  80.     if (module->defall || module->defplayers)
  81.       write_players(fp, module);
  82.     if (module->defall || module->defunits)
  83.       write_units(fp, module);
  84.     if (module->defall || module->defhistory)
  85.       write_history(fp, module);
  86.     /* Write the game notes here (seems reasonable, no deeper reason). */
  87.     if (module->instructions != lispnil) {
  88.         start_form(fp, key(K_GAME_MODULE));  space_form(fp);
  89.         write_lisp_prop(fp, key(K_INSTRUCTIONS), module->instructions,
  90.                 lispnil, 0, FALSE, 1);
  91.         newline_form(fp);  end_form(fp);  newline_form(fp);  newline_form(fp);
  92.     }
  93.     if (module->notes != lispnil) {
  94.         start_form(fp, key(K_GAME_MODULE));  space_form(fp);
  95.         write_lisp_prop(fp, key(K_NOTES), module->notes,
  96.                 lispnil, 0, FALSE, 1);
  97.         newline_form(fp);  end_form(fp);  newline_form(fp);  newline_form(fp);
  98.     }
  99.     if (module->designnotes != lispnil) {
  100.         start_form(fp, key(K_GAME_MODULE));  space_form(fp);
  101.         write_lisp_prop(fp, key(K_DESIGN_NOTES), module->designnotes,
  102.                 lispnil, 0, FALSE, 1);
  103.         newline_form(fp);  end_form(fp);  newline_form(fp);  newline_form(fp);
  104.     }
  105.     fclose(fp);
  106.     return TRUE;
  107.     } else {
  108.     return FALSE;
  109.     }
  110. }
  111.  
  112. /* Write definitions of all the types. */
  113.  
  114. write_types(fp, module)
  115. FILE *fp;
  116. Module *module;
  117. {
  118.     int complete = FALSE;
  119.     int u, m, t, i, ival;
  120.     char *sval;
  121.     Obj *obj;
  122.  
  123.     /* (or write out all the default values first for doc, then
  124.        only write changed values) */
  125.  
  126.     for_all_unit_types(u) {
  127.     start_form(fp, key(K_UNIT_TYPE));
  128.     add_to_form(fp, shortest_unique_name(u));
  129.     newline_form(fp);
  130.     for (i = 0; utypedefns[i].name != NULL; ++i) {
  131.         if (utypedefns[i].intgetter) {
  132.         ival = (*(utypedefns[i].intgetter))(udexes1[200], randoms[200];
  133.  
  134.     start_form(fp, key(K_TABLE));
  135.     add_to_form(fp, name);
  136.     fprintf(fp, "  ; %d", dflt);
  137.     /* Choose the index that will result in fewest rows. */
  138.     if (dim1 <= dim2) {
  139.     for (k = 0; k < dim1; ++k) indexes1[k] = FALSE;
  140.     for (i = 0; i < dim1; ++i) {
  141.         /* First see if this row has all the same values as the next one. */
  142.         indexes1[i] = TRUE;
  143.         nextrowdiffers = FALSE;
  144.         if (i < dim1 - 1) {
  145.             for (j = 0; j < dim2; ++j) {
  146.                 if ((*getter)(i, j) != (*getter)(i + 1, j)) {
  147.                     nextrowdiffers = TRUE;
  148.                     break;
  149.                 }
  150.             }
  151.         } else {
  152.             /* The last row is *always* "different". */
  153.             nextrowdiffers = TRUE;
  154.         }
  155.         if (nextrowdiffers) {
  156.             /* Make a histogram of all the values in this row. */
  157.             mostcommon[0].count = 1;  mostcommon[0].val = (*getter)(i, 0);
  158.             next = 1;
  159.             for (j = 0; j < dim2; ++j) {
  160.             for (k = 0; k < next; ++k) {
  161.                 if (mostcommon[k].val == (*getter)(i, j)) {
  162.                     ++(mostcommon[k].count);
  163.                     break;
  164.                 }
  165.             }
  166.             if (k == next) {
  167.                 mostcommon[next].count = 1;  mostcommon[next].val = (*getter)(i, j);
  168.                 ++next;
  169.             }
  170.             }
  171.             if (next == 1 && mostcommon[0].val == dflt) {
  172.                 /* Entire row(s) is just the default table value. */
  173.             } else {
  174.                 allsame = FALSE;
  175.                 numrandoms = 0;
  176.             if (next == 1) {
  177.                 allsame = TRUE;
  178.             } else {
  179.                 qsort(mostcommon, next, sizeof(struct histo), histo_compare);
  180.                 if (mostcommon[0].count < (3 * dim2) / 4) {
  181.                 } else {
  182.                     allsame = TRUE;
  183.                 for (j = 0; j < dim2; ++j) {
  184.                     randoms[j] = (mostcommon[0].val != (*getter)(i, j));
  185.                     if (randoms[j]) ++numrandoms;
  186.                 }
  187.                 }
  188.             }
  189.             if (mostcommon[0].val != dflt) {
  190.                 fprintf(fp, "\n  (");
  191.                 write_type_name_list(fp, typ1, indexes1, dim1);
  192.                 fprintf(fp, " %s ", star_from_typ(typ2));
  193.                 if (allsame) {
  194.                         fprintf(fp, "%d", mostcommon[0].val);
  195.                 } else {
  196.                         write_type_value_list(fp, typ2, NULL, dim2, getter, i);
  197.                 }
  198.                 fprintf(fp, ")");
  199.             }
  200.             if (numrandoms > 0) {
  201.                 fprintf(fp, "\n  (");
  202.                 write_type_name_list(fp, typ1, indexes1, dim1);
  203.                 fprintf(fp, " ");
  204.                 write_type_name_list(fp, typ2, randoms, dim2);
  205.                 fprintf(fp, " ");
  206.                 write_type_value_list(fp, typ2, randoms, dim2, getter, i);
  207.                 fprintf(fp, ")");
  208.             }
  209.             }
  210.             for (k = 0; k < dim1; ++k) indexes1[k] = FALSE;
  211.         }
  212.     }
  213.     } else {
  214.     for (i = 0; i < dim2; ++i) {
  215.         constcol = TRUE;
  216.         colvalue = (*getter)(0, i);
  217.         for (j = 0; j < dim1; ++j) {
  218.         if ((*getter)(j, i) != colvalue) {
  219.             constcol = FALSE;
  220.             break;
  221.         }
  222.         }
  223.         if (!constcol || colvalue != dflt) {
  224.         fprintf(fp, "\n  (%s %s",
  225.             star_from_typ(typ1),
  226.             escaped_symbol(name_from_typ(typ2, i)));
  227.         if (constcol) {
  228.             fprintf(fp, " %d", colvalue);
  229.         } else {
  230.             fprintf(fp, " (");
  231.             for (j = 0; j < dim1; ++j) {
  232.             fprintf(fp, " %d", (*getter)(j, i));
  233.             }
  234.             fprintf(fp, ")");
  235.         }
  236.         fprintf(fp, ")");
  237.         }
  238.     }
  239.     }
  240.     end_form(fp);  newline_form(fp);
  241. }
  242.  
  243. /* Write info about the whole world. */
  244.  
  245. write_world(fp, module)
  246. FILE *fp;
  247. Module *module;
  248. {
  249.     newline_form(fp);
  250.     start_form(fp, key(K_WORLD));
  251.     fprintf(fp, " %d",
  252.         (doreshape ? reshaper->finalcircumference : world.circumference));
  253.     write_num_prop(fp, key(K_DAY_LENGTH), world.daylength, 1, 0, 1);
  254.     write_num_prop(fp, key(K_YEAR_LENGTH), world.yearlength, 1, 0, 1);
  255.     end_form(fp);  newline_form(fp);
  256. }
  257.  
  258. /* Write info about the area in the world.  This code uses run-length encoding
  259.    to reduce the size of each written layer as much as possible.  Note
  260.    also that each layer is written as a separate form, so that the Lisp
  261.    reader doesn't have to read really large forms back in. */
  262.  
  263. write_areas(fp, module)
  264. FILE *fp;
  265. Module *module;
  266. {
  267.     int all = module->defall, compress = module->compresslayers;
  268.  
  269.     newline_form(fp);
  270.     /* Write the basic dimensions. */
  271.     start_form(fp, key(K_AREA));
  272.     add_num_to_form(fp, (doreshape ? reshaper->finalwidth : area.width));
  273.     add_num_to_form(fp, (doreshape ? reshaprite %d players ...\n", numplayers);
  274.     for_all_sides(side) {
  275.     if ((player = side->player) != NULL) {
  276.         write_player(fp, player);
  277.         Dprintf("Wrote player %s,\n", player_desig(player));
  278.     }
  279.     }
  280.     Dprintf("... Done writing players.\n");
  281. }
  282.  
  283. write_player(fp, player)
  284. FILE *fp;
  285. Player *player;
  286. {
  287.     start_form(fp, key(K_PLAYER));  fprintf(fp, " %d", 0);  newline_form(fp);
  288.     write_str_prop(fp, key(K_NAME), player->name, "", 0, 1);
  289.     write_str_prop(fp, key(K_CONFIG_NAME), player->configname, "", 0, 1);
  290.     write_str_prop(fp, key(K_DISPLAY_NAME), player->displayname, "", 0, 1);
  291.     write_str_prop(fp, key(K_AI_TYPE_NAME), player->aitypename, "", 0, 1);
  292.     end_form(fp);  newline_form(fp);
  293. }
  294.  
  295. /* Should write out "unit groups" with dict prepended, then can use with
  296.    multiple games */
  297.  
  298. /* Write the unit section of a game module. */
  299.  
  300. write_units(fp, module)
  301. FILE *fp;
  302. Module *module;
  303. {
  304.     int x, y;
  305.     Unit *unit;
  306.     Side *loopside;
  307.  
  308.     /* Make sure no dead units get saved. */
  309.     flush_dead_units();
  310.     /* Make a consistent ordering. */
  311.     sort_units();
  312.     fprintf(fp, "; %d units\n", numunits);
  313.     /* Need to write out the defaults being assumed subsequently. */
  314.     /* maybe use those in postprocessing. */
  315.     fprintf(fp, "(unit-defaults)\n");
  316.     Dprintf("Writing %d units ...\n", numunits);
  317.     for_all_sides_plus_indep(loopside) {
  318.       for_all_side_units(loopside, unit) {
  319.     if (1 /* test unit for worthiness to be written */) {
  320.         if (doreshape) {
  321.         reshaped_point(unit->x, unit->y, &x, &y);
  322.         } else {
  323.         x = unit->x;  y = unit->y;
  324.         }
  325.         start_form(fp, shortest_unique_name(unit->type));
  326.         fprintf(fp, " %d %d %d", x, y, side_number(unit->side));
  327.         write_num_prop(fp, key(K_Z), unit->z, 0, 0, 0);
  328.         write_str_prop(fp, key(K_N), unit->name, NULL, 0, 0);
  329.         /* Maybe write the unit's id. */
  330.         if (module->defall || module->defunitids || unit->occupant) {
  331.         write_num_prop(fp, key(K_SHARP), unit->id, 0, 0, 0);
  332.         }
  333.         /* Need this to get back into the right transport. */
  334.         if (unit->transport) {
  335.         write_num_prop(fp, key(K_IN), unit->transport->id, 0, 0, 0);
  336.         }
  337.         /* Write optional info about the units. */
  338.         if (module->defall || module->defunitprops)
  339.           write_unit_properties(unit, fp);
  340.         if (module->defall || module->defunitacts)
  341.           write_unit_act(unit, fp);
  342.         if (module->defall || module->defunitplans)
  343.           write_unit_plan(unit, fp);
  344.         /* close the unit out */
  345.         end_form(fp);
  346.         newline_form(fp);
  347.         Dprintf("Wrote %s\n", unit_desig(unit));
  348.     }
  349.       }
  350.       newline_form(fp);
  351.     }
  352.     Dprintf("... Done writing units.\n");
  353. }
  354.  
  355. /* Write random properties, but only if they have non-default values. */
  356.  
  357. write_unit_properties(unit, fp)
  358. Unit *unit;
  359. FILE *fp;
  360. {
  361.     int m, allfull = TRUE;
  362.  
  363.     write_num_prop(fp, key(K_NM), unit->number, 0, 0, 0);
  364.     write_num_prop(fp, key(K_HP), unit->hp, u_hp(unit->type), 0, 0);
  365.     write_num_prop(fp, key(K_CP), unit->cp, u_cp(unit->type), 0, 0);
  366.     write_num_prop(fp, key(K_CXP), unit->cxp, 0, 0, 0);
  367.     write_utype_value_list(fp, key(K_TP), unit->tooling, 0);
  368.     /* (should use general write mtype value list) */
  369.     if (nummtypes > 0) {
  370.     for_all_material_types(m) {
  371.         if (unit->supply[m] < um_storage(unit->type, m)) {
  372.         allfull = FALSE;
  373.         break;
  374.         }
  375.     }
  376.     if (!allfull) {
  377.         start_form(fp, key(K_M));
  378.         if (1 /* write all of them */) {
  379.         for_all_material_types(m) {
  380.             fprintf(fp, " %d", unit->supply[m]);
  381.         }
  382.         } else {
  383.             /* (should write a named list) */
  384.         }
  385.         end_form(fp);
  386.     }
  387.     }
  388.     write_lisp_prop(fp, key(K_X), unit->hook, lispnil, 0, TRUE, FALSE);
  389. }
  390.  
  391. /* Write out the unit's current actor state. */
  392.  
  393. write_unit_act(unit, fp)
  394. Unit *unit;
  395. FILE *fp;
  396. {
  397.     int acp = u_acp(unit->type), atype, i;
  398.     ActorState *act = unit->act;
  399.  
  400.     if (act != NULL
  401.     && (act->acp != acp
  402.         || act->initacp != acp
  403.         || act->nextaction.type != A_NONE)) {
  404.     if (1) {
  405.        newline_form(fp);  space_form(fp);
  406.     }
  407.     space_form(fp);
  408.     start_form(fp, key(K_ACT));
  409.     if (act->acp != acp) /* dubious */
  410.       write_num_prop(fp, key(K_ACP), act->